package edu.washington.cs.gitanaly;

import java.io.IOException;

import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.TreeFilter;

public class MethodDiffFilter extends TreeFilter {

	private Repository repo;
	
	private String path;
	
	private String typeName;
	
	private String methodName;
	
	public MethodDiffFilter(Repository repo, String path, String typeName, String methodName) {
		this.repo = repo;
		this.path = path;
		this.typeName = typeName;
		this.methodName = methodName;
	}
	
	@Override
	public TreeFilter clone() {
		return this;
	}

	@Override
	public boolean include(TreeWalk treeWalk) throws MissingObjectException, IncorrectObjectTypeException, IOException {
		int n = treeWalk.getTreeCount();
		
		if (n == 1) {
			if (treeWalk.getPathString().equals(path)) {
				boolean hasThisMethod = Util.hasThisMethod(repo, treeWalk, 0, typeName, methodName);
//				System.out.println(hasThisMethod);
				if (hasThisMethod) {
					return true;
				} else {
					return false;
				}
			}
			return true;
		}
		
		int m = treeWalk.getRawMode(0);
		
		for (int i = 1; i < n; ++i) {
			if (treeWalk.getRawMode(i) == m && treeWalk.idEqual(0, i)) {
				return false;
			}
		}
		
		if (treeWalk.getPathString().equals(path)) {
			boolean hasThisMethod = Util.hasThisMethod(repo, treeWalk, 0, typeName, methodName);
//			System.out.println(hasThisMethod);

			if (hasThisMethod) {
				boolean flag = true;
				for (int i = 1; i < n; ++i) {
					if (Util.hasThisMethod(repo, treeWalk, i, typeName, methodName)) {
						flag = false;
						break;
					}
				}
				return flag;
			} else {
				boolean flag = true;
				for (int i = 1; i < n; ++i) {
					if (!Util.hasThisMethod(repo, treeWalk, i, typeName, methodName)) {
						flag = false;
						break;
					}
				}
				return flag;
			}
		}
		return true;
	}

	@Override
	public boolean shouldBeRecursive() {
		return true;
	}
	
	
}
